﻿using OpenTK.Mathematics;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.Threading.Tasks;

namespace Core.ECS.Components
{
    [DataContract]
    public class CBoxCollider : IComponent
    {
        public Guid Id
        {
            get => _id;
            set => _id = value;
        }
        [DataMember]
        private Guid _id;
        public Vector3 Dimensions
        {
            get => _dimensions;
            set => _dimensions = value;
        }
        public Actor? Actor => Actor.GetActor(Id);
        [DataMember]
        private Vector3 _dimensions;

        public static bool CheckCollider(CBoxCollider collider1, CBoxCollider collider2)
        {
            if(collider1 == null || collider2 == null) return false;
            var transform1 = collider1.Actor?.Transform;
            var transform2 = collider2.Actor?.Transform;

            if (transform1 == null || transform2 == null)
            {
                return false;
            }

            // 获取长方体1的顶点
            Vector3[] vertices1 = GetCuboidVertices(transform1.WorldPosition, collider1.Dimensions * transform1.WorldScale, transform1.WorldRotation);

            // 获取长方体2的顶点
            Vector3[] vertices2 = GetCuboidVertices(transform2.WorldPosition, collider2.Dimensions * transform2.WorldScale, transform2.WorldRotation);

            // 获取长方体2的面法向量
            Vector3[] normals2 = GetFaceNormals(vertices2);

            // 检查长方体1的每个顶点是否都在长方体2的任意一个面的同一侧
            foreach (var vertex1 in vertices1)
            {
                bool isOutsideAllFaces = true;
                foreach (var normal in normals2)
                {
                    bool isAllVerticesOnSameSide = true;
                    float referenceDot = Vector3.Dot(normal, vertices2[0] - vertex1);
                    for (int i = 1; i < vertices2.Length; i++)
                    {
                        float dot = Vector3.Dot(normal, vertices2[i] - vertex1);
                        if (referenceDot * dot < 0)
                        {
                            isAllVerticesOnSameSide = false;
                            break;
                        }
                    }
                    if (isAllVerticesOnSameSide)
                    {
                        isOutsideAllFaces = false;
                        break;
                    }
                }
                if (isOutsideAllFaces)
                {
                    return false;
                }
            }

            return true;
        }

        public static Vector3[] GetCuboidVertices(Vector3 center, Vector3 halfLengths, Quaternion rotation)
        {
            Vector3[] localVertices = new Vector3[]
            {
                new Vector3(-1, -1, -1),
                new Vector3(1, -1, -1),
                new Vector3(1, 1, -1),
                new Vector3(-1, 1, -1),
                new Vector3(-1, -1, 1),
                new Vector3(1, -1, 1),
                new Vector3(1, 1, 1),
                new Vector3(-1, 1, 1)
            };

            for (int i = 0; i < localVertices.Length; i++)
            {
                localVertices[i] *= halfLengths;
                localVertices[i] = Vector3.Transform(localVertices[i], rotation);
                localVertices[i] += center;
            }

            return localVertices;
        }

        public static Vector3[] GetFaceNormals(Vector3[] vertices)
        {
            Vector3[] normals = new Vector3[6];

            normals[0] = Vector3.Normalize(Vector3.Cross(vertices[1] - vertices[0], vertices[2] - vertices[1])); // Front face
            normals[1] = Vector3.Normalize(Vector3.Cross(vertices[5] - vertices[4], vertices[6] - vertices[5])); // Back face
            normals[2] = Vector3.Normalize(Vector3.Cross(vertices[4] - vertices[0], vertices[3] - vertices[4])); // Left face
            normals[3] = Vector3.Normalize(Vector3.Cross(vertices[2] - vertices[1], vertices[6] - vertices[2])); // Right face
            normals[4] = Vector3.Normalize(Vector3.Cross(vertices[3] - vertices[0], vertices[1] - vertices[3])); // Bottom face
            normals[5] = Vector3.Normalize(Vector3.Cross(vertices[7] - vertices[4], vertices[5] - vertices[7])); // Top face

            return normals;
        }
    }
}

